home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / OCCTRL.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  31KB  |  1,321 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // (c) Copyright 1997 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.24  $
  6. //
  7. // Implementation of the TOcControl Class and helpers
  8. // These class encapsulate the hosting of OCX controls...
  9. //----------------------------------------------------------------------------
  10. #include <ocf/pch.h>
  11. #if !defined(OCF_OLEUTIL_H)
  12. # include <ocf/oleutil.h>
  13. #endif
  14. #if !defined(OCF_OCSTORAG_H)
  15. # include <ocf/ocstorag.h>
  16. #endif
  17. #if !defined(OCF_OCDOC_H)
  18. # include <ocf/ocdoc.h>
  19. #endif
  20. #if !defined(OCF_OCAPP_H)
  21. # include <ocf/ocapp.h>
  22. #endif
  23. #if !defined(OCF_OCVIEW_H)
  24. # include <ocf/ocview.h>
  25. #endif
  26. #if !defined(OCF_OCCTRL_H)
  27. # include <ocf/occtrl.h>
  28. #endif
  29. #if !defined(OCF_AUTODEFS_H)
  30. # include <ocf/autodefs.h>
  31. #endif
  32. #if !defined(OCF_AUTOMACR_H)
  33. # include <ocf/automacr.h>
  34. #endif
  35.  
  36.  
  37. // Routine to convert TOcControl* to TOcxView* [treated as opaque pointers]
  38. // for exposing delegated properties..
  39. //
  40. static ObjectPtr
  41. GetControlView(ObjectPtr ctl);
  42.  
  43. //
  44. //
  45. //
  46. TEventEntry::TEventEntry() : IDOfEvent(0), ParamCount(0), NameAndParams(0)
  47. {}
  48.  
  49. //
  50. //
  51. //
  52. TEventEntry::~TEventEntry()
  53. {
  54.   Cleanup();
  55. }
  56.  
  57. //
  58. // NOTE: Does not invoke 'Cleanup' before initializing data member with
  59. //       newly retrieved information. Invoke 'Cleanup' explicitly if
  60. //       object has already retrieved event information.
  61. //
  62. void
  63. TEventEntry::Init(int index, ITypeInfo* typeInfo)
  64. {
  65.   PRECONDITION(typeInfo);
  66.   LPFUNCDESC funcDesc= 0;
  67.   if (SUCCEEDED(typeInfo->GetFuncDesc(index, &funcDesc))) {
  68.     CHECK(funcDesc);
  69.     IDOfEvent = funcDesc->memid;
  70.     ParamCount= funcDesc->cParams;
  71.     NameAndParams= new BSTR[funcDesc->cParams+1];
  72.  
  73.     uint i;
  74.     typeInfo->GetNames(funcDesc->memid, NameAndParams,
  75.                        funcDesc->cParams+1, &i);
  76.     CHECK(i == funcDesc->cParams+1);
  77.     typeInfo->ReleaseFuncDesc(funcDesc);
  78.   }
  79. }
  80.  
  81. //
  82. //
  83. //
  84. void
  85. TEventEntry::Cleanup()
  86. {
  87.   if (NameAndParams) {
  88.     for (int i=0; i<=ParamCount; i++)
  89.       ::SysFreeString(NameAndParams[i]);
  90.     delete [] NameAndParams;
  91.     NameAndParams = 0;
  92.   }
  93. }
  94.  
  95. //
  96. //
  97. //
  98. TEventList::TEventList(ITypeInfo* eventTypeInfo)
  99.            :EventList(0), Count(0), EventIID(CLSID_NULL)
  100. {
  101.   PRECONDITION(eventTypeInfo);
  102.  
  103.   LPTYPEATTR tAttr = 0;
  104.   if (SUCCEEDED(eventTypeInfo->GetTypeAttr(&tAttr))) {
  105.     EventIID = tAttr->guid;
  106.     Count = tAttr->cFuncs;
  107.     if (Count) {
  108.       EventList = new TEventEntry[Count];
  109.       for (int i=0; i<Count; i++)
  110.         EventList[i].Init(i, eventTypeInfo);
  111.     }
  112.     eventTypeInfo->ReleaseTypeAttr(tAttr);
  113.   }
  114. }
  115.  
  116. //
  117. //
  118. //
  119. TEventList::~TEventList()
  120. {
  121.   delete [] EventList;
  122. }
  123.  
  124. //
  125. //
  126. //
  127. TEventEntry&
  128. TEventList::operator[](int index) {
  129.   PRECONDITION(index < Count);
  130.   PRECONDITION(EventList);
  131.   return EventList[index];
  132. }
  133.  
  134. //
  135. // Control container ambient property support
  136. //
  137. DEFINE_AUTOCLASS(TOcxView)
  138.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_BACKCOLOR,        BackColor,        TAutoLong,   "!BackColor",        "@BackColor_", 0)
  139.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_FORECOLOR,        ForeColor,        TAutoLong,   "!ForeColor",        "@ForeColor_", 0)
  140.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_LOCALEID,         LocaleID,         TAutoLong,   "!LocaleID",         "@LocaleID_",  0)
  141.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_TEXTALIGN,        TextAlign,        TAutoShort,  "!TextAlign",        "@TextAlign_", 0)
  142.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_MESSAGEREFLECT,   MessageReflect,   TAutoBool,   "!MessageReflect",   "@MsgReflect_",  0)
  143.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_USERMODE,         UserMode,         TAutoBool,   "!UserMode",         "@UserMode_",  0)
  144.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_UIDEAD,           UIDead,           TAutoBool,   "!UIDead",           "@UIDead_",    0)
  145.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_SHOWGRABHANDLES,  ShowGrabHandles,  TAutoBool,   "!ShowGrabHandles",  "@GrabHdl_",   0)
  146.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_SHOWHATCHING,     ShowHatching,     TAutoBool,   "!ShowHatching",     "@ShowHat_", 0)
  147.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_DISPLAYASDEFAULT, DisplayAsDefault, TAutoBool,   "!DisplayAsDefault", "@DispDef_",  0)
  148.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_SUPPORTSMNEMONICS,SupportsMnemonics,TAutoBool,   "!SupportsMnemonics","@Mnemonics_", 0)
  149.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_DISPLAYNAME,      DisplayName,      TAutoString, "!DisplayName",      "@DispName_",  0)
  150.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_SCALEUNITS,       ScaleUnits,       TAutoString, "!ScaleUnits",       "@ScaleUnits_",0)
  151.   EXPOSE_PROPRW_ID(DISPID_AMBIENT_FONT,             Font,             TAutoDispatch,"!Font",            "@Font_",      0)
  152. END_AUTOCLASS(TOcxView, tfNormal, "TOcxView",   "@TOcxView_", 0)
  153.  
  154. //
  155. // Control standard extended properties and standard events
  156. //
  157. DEFINE_AUTOCLASS(TOcControl)
  158.   //
  159.   // Standard extended properties
  160.   //
  161.   EXPOSE_PROPRO_ID(0x80010008L,   Parent,  TAutoDispatch,"!Parent",     "!Parent",   0)
  162.   EXPOSE_PROPRW_ID(0x80010007L,   Visible, TAutoBool,    "!Visible",    "!Visible",  0)
  163.   EXPOSE_PROPRW_ID(0x80010037L,   Cancel,  TAutoBool,    "!Cancel",     "@Cancel_",  0)
  164.   EXPOSE_PROPRW_ID(0x80010038L,   Default, TAutoBool,    "!Default",    "@Default_", 0)
  165.   EXPOSE_PROPRW_ID(0x80010000L,   Name,    TAutoString,  "!Name",       "@ObjName_", 0)
  166.   EXPOSE_PROPRW_ID(0x80010100L,   Left,     TAutoLong,   "!Left",       "!Left",     0)
  167.   EXPOSE_PROPRW_ID(0x80010101L,   Top,      TAutoLong,   "!Top",        "!Top",      0)
  168.   EXPOSE_PROPRW_ID(0x80010102L,   Width,    TAutoLong,   "!Width",      "!Width",    0)
  169.   EXPOSE_PROPRW_ID(0x80010103L,   Height,   TAutoLong,   "!Height",     "!Height",   0)
  170.  
  171.   // Expose ambient properties
  172.   //
  173.   EXPOSE_DELEGATE(TOcxView, "TOcxView",  GetControlView)
  174.  
  175. END_AUTOCLASS(TOcControl, tfNormal, "TOcControl",   "@TOcControl_", 0)
  176.  
  177.  
  178. //
  179. // Control standard extended properties and standard events
  180. //
  181. DEFINE_AUTOCLASS(TOcControlEvent)
  182.   //
  183.   // Standard events
  184.   //
  185.   EXPOSE_METHOD_ID(DISPID_CLICK,     Click,    TAutoLong,  "!Click",     "@Click_",     0)
  186.   EXPOSE_METHOD_ID(DISPID_DBLCLICK,  DblClick, TAutoLong,  "!DblClick",  "@DblClick_",  0)
  187.   EXPOSE_METHOD_ID(DISPID_MOUSEDOWN, MouseDown,TAutoLong,  "!MouseDown", "@MouseDown_", 0)
  188.     REQUIRED_ARG(TAutoShort, "!Button")
  189.     REQUIRED_ARG(TAutoShort, "!Shift")
  190.     REQUIRED_ARG(TAutoLong,  "!X")
  191.     REQUIRED_ARG(TAutoLong,  "!Y")
  192.   EXPOSE_METHOD_ID(DISPID_MOUSEUP,   MouseUp,  TAutoLong,  "!MouseUp",  "@MouseUp_",  0)
  193.     REQUIRED_ARG(TAutoShort, "!Button")
  194.     REQUIRED_ARG(TAutoShort, "!Shift")
  195.     REQUIRED_ARG(TAutoLong,  "!X")
  196.     REQUIRED_ARG(TAutoLong,  "!Y")
  197.   EXPOSE_METHOD_ID(DISPID_MOUSEMOVE, MouseMove,TAutoLong,  "!MouseMove", "@MouseMove_", 0)
  198.     REQUIRED_ARG(TAutoShort, "!Button")
  199.     REQUIRED_ARG(TAutoShort, "!Shift")
  200.     REQUIRED_ARG(TAutoLong,  "!X")
  201.     REQUIRED_ARG(TAutoLong,  "!Y")
  202.   EXPOSE_METHOD_ID(DISPID_KEYDOWN, KeyDown, TAutoLong,  "!KeyDown", "@KeyDown_", 0)
  203.     REQUIRED_ARG(TAutoShortRef, "!KeyCode")
  204.     REQUIRED_ARG(TAutoShort, "!Shift")
  205.   EXPOSE_METHOD_ID(DISPID_KEYUP, KeyUp, TAutoLong,  "!KeyUp", "@KeyUp_", 0)
  206.     REQUIRED_ARG(TAutoShortRef, "!KeyCode")
  207.     REQUIRED_ARG(TAutoShort, "!Shift")
  208.   EXPOSE_METHOD_ID(DISPID_ERROREVENT, ErrorEvent, TAutoLong, "!ErrorEvent","&ErrorEvent_",0)
  209.     REQUIRED_ARG(TAutoShort, "!Number")
  210.     REQUIRED_ARG(TAutoString,"!Description")
  211.     REQUIRED_ARG(TAutoLong,  "!SCode")
  212.     REQUIRED_ARG(TAutoString,"!Source")
  213.     REQUIRED_ARG(TAutoString,"!HelpFile")
  214.     REQUIRED_ARG(TAutoLong,  "!HelpContext")
  215.     REQUIRED_ARG(TAutoBoolRef,"!CancelDisplay")
  216.   EXPOSE_METHOD_ID(DISPID_CATCH_ALL, CustomEvent,  TAutoLong, "!CustomEvent", "@CustomEvent_",0)
  217.     REQUIRED_ARG(TAutoLongRef, "!Number")
  218.  
  219. END_AUTOCLASS(TOcControlEvent, tfNormal, "TOcControlEvent",   "@TOcCtrlEvent_", 0)
  220.  
  221. //
  222. //
  223. //
  224. ObjectPtr GetControlView(ObjectPtr ctl)
  225. {
  226.   return (ObjectPtr)((TOcControl*)ctl)->GetActiveControlView();
  227. }
  228.  
  229. //
  230. // Construct a new part with a given temp id
  231. //
  232. TOcControl::TOcControl(TOcDocument& document, int id, TOcControlEvent* pEv)
  233.            :TOcPart(document, id), pUserName(new TString), BCtrlI(0),
  234.             pIExtended(0), pEvents(pEv), EventList(0)
  235. {
  236.   *pUserName = GetName();
  237. }
  238.  
  239. //
  240. // Construct a part from a named stream in an oc doc's storage
  241. //
  242. TOcControl::TOcControl(TOcDocument& document, const char far* name)
  243.            :TOcPart(document, name), pUserName(0), BCtrlI(0), pIExtended(0),
  244.             pEvents(0), EventList(0)
  245. {
  246. }
  247.  
  248. //
  249. //
  250. //
  251. TOcControl::~TOcControl()
  252. {
  253.   if (pIExtended)
  254.     pIExtended->Release();
  255.   delete pUserName;
  256.   delete EventList;
  257. }
  258.  
  259. //
  260. //
  261. //
  262. bool
  263. TOcControl::Init(TOcInitInfo far* initInfo, TRect objPos)
  264. {
  265.   return TOcPart::Init(initInfo, objPos);
  266. }
  267.  
  268. //
  269. // Perform common ctor initialization
  270. //
  271. bool
  272. TOcControl::InitObj(TOcInitInfo far* initInfo)
  273. {
  274.   if (TOcPart::InitObj((TOcInitInfo far *)NULL) == false)
  275.     return false;
  276.  
  277.   if (initInfo) {
  278.     if (!pIExtended)
  279.       (TUnknown far*)pIExtended = CreateAutoObject(this, ClassInfo);
  280.  
  281.     if (!pEvents)
  282.       pEvents = new TOcControlEvent();
  283.  
  284.     // There must be an IStorage associated with each part, make sure the
  285.     // ctor got it OK
  286.     //
  287.     initInfo->Storage = Storage->GetIStorage();
  288.  
  289.     // Create part helper
  290.     //
  291.     TXObjComp::Check(
  292.       OcDocument.OcApp.BOleComponentCreate(&BPart, GetOuter(), cidBOleControl),
  293.       TXObjComp::xInternalPartError);
  294.  
  295.     // Get the interfaces we need & then release the object itself
  296.     //
  297.     if (HRSucceeded(BPart->QueryInterface(IID_IBPart, &(LPVOID)BPartI)))
  298.       BPartI->Release();
  299.     if (HRSucceeded(BPart->QueryInterface(IID_IBLinkable, &(LPVOID)BLPartI)))
  300.       BLPartI->Release();
  301.     if (HRSucceeded(BPart->QueryInterface(IID_IBControl, &(LPVOID)BCtrlI)))
  302.       BCtrlI->Release();
  303.  
  304.     // Initialize the Extended/Ambient IDispatch
  305.     //
  306.     HRESULT hr;
  307.     IBSite* BSiteI;
  308.     hr = QueryInterface(IID_IBSite, &(LPVOID)BSiteI);
  309.     if (HRSucceeded(hr)) {
  310.       IDispatch* pID = 0;
  311.       TOcView*   activeView = OcDocument.GetActiveView();
  312.       CHECK(activeView);
  313.       if ((pIExtended) &&(SUCCEEDED(pIExtended->QueryObject(IID_IDispatch,
  314.                                      &(VOID FAR*)pID)))) {
  315.         BCtrlI->SetAmbientDispatch(pID);
  316.         pID->Release();
  317.       }
  318.  
  319.       // Init the part
  320.       //
  321.       if (!BPartI || !HRSucceeded(hr = BPartI->Init(BSiteI, initInfo))) {
  322.         BSiteI->Release();
  323.         BPart->Release();
  324.         BPart = 0;
  325.         TXObjComp::Throw(TXObjComp::xPartInitError, hr);
  326.       }
  327.       BSiteI->Release();
  328.  
  329.       Rename();
  330.       if (initInfo->How == ihLink)  // Remember that we are a link
  331.         Flags |= Link;
  332.  
  333.       // Initialize the Events IDispatch
  334.       //
  335.       SetEventDispatch();
  336.  
  337.       // New parts become active when they are init'd above. Make sure that
  338.       // our view knows that we are active too.
  339.       //
  340.       if (initInfo->Where == iwNew) {
  341.         Flags |= Active;
  342.         activeView->ActivatePart(this);
  343.       }
  344.     }
  345.     else
  346.       TXObjComp::Throw(TXObjComp::xPartInitError, hr);
  347.  
  348.   }
  349.   return true;
  350. }
  351.  
  352. //
  353. // Retrieves the ITypeInfo the 'default source' event object of this
  354. // control.
  355. // NOTE: Receiver must 'Release' the returned object, if successful.
  356. //
  357. ITypeInfo*
  358. TOcControl::GetEventTypeInfo()
  359. {
  360.   ITypeInfo* pRet = NULL;
  361.   if (GetBControlI())
  362.     GetBControlI()->GetEventTypeInfo(&pRet);
  363.   return pRet;
  364. }
  365.  
  366. //
  367. // Retrieves a list of events generated by this control.
  368. // Returns true if the event list was successfully retrieved.
  369. //
  370. bool
  371. TOcControl::FillEventList()
  372. {
  373.   // Skip if we've already retrieved the event list
  374.   //
  375.   if (EventList && EventList->GetCount())
  376.     return true;
  377.  
  378.   // Retrieve Event ITypeInfo
  379.   //
  380.   ITypeInfo* eventTypeInfo = GetEventTypeInfo();
  381.   if (!eventTypeInfo)
  382.     return false;
  383.  
  384.   // Allocate new EventList object
  385.   //
  386.   EventList = new TEventList(eventTypeInfo);
  387.   eventTypeInfo->Release();
  388.   return true;
  389. }
  390.  
  391. //
  392. //
  393. //
  394. TEventList*
  395. TOcControl::GetEventList() const
  396. {
  397.   return EventList;
  398. }
  399.  
  400. //
  401. // Retrieves the primary IDispatch of the control.
  402. // NOTE: Receiver must 'Release' the returned object, if successful.
  403. //
  404. IDispatch*
  405. TOcControl::GetCtlDispatch()
  406. {
  407.   IDispatch* pDisp = 0;
  408.   if (GetBControlI())
  409.     GetBControlI()->GetCtrlDispatch(&pDisp);
  410.   return pDisp;
  411. }
  412.  
  413. //
  414. //
  415. //
  416. void
  417. TOcControl::SetEventDispatch()
  418. {
  419.   if (!pEvents)
  420.     return;
  421.  
  422.   pEvents->pCtrl = this;
  423.   pEvents->InitEventDispatch();
  424.  
  425.   IDispatch*     pID = 0;
  426.   TServedObject* pS = pEvents->pIEvents;
  427.   if (SUCCEEDED(pS->QueryObject(IID_IDispatch, (void**)&pID))) {
  428.     IID iidEv;
  429.  
  430.     BCtrlI->GetEventIID(&iidEv);
  431.     pS->iidEvent = iidEv;
  432.  
  433.     ITypeInfo* pITypeInfo;
  434.     LPTYPEATTR pTA;
  435.     UINT       i;
  436.     UINT       cEvents;
  437.  
  438.     BCtrlI->GetEventTypeInfo(&pITypeInfo);
  439.     if (pITypeInfo)  {
  440.       pITypeInfo->GetTypeAttr(&pTA);
  441.       if (pTA) {
  442.         cEvents = pTA->cFuncs;
  443.         pITypeInfo->ReleaseTypeAttr(pTA);
  444.         for (i = 0; i < cEvents; i++) {
  445.           LPFUNCDESC    pFD;
  446.  
  447.           if (SUCCEEDED(pITypeInfo->GetFuncDesc(i, &pFD))) {
  448.             ObjectPtr object = this;  // copy in case of ptr adjustment
  449.  
  450.             // see if we have a method associated with this DISPID
  451.             // if not, find one with the same name and see if the
  452.             // number of parameters matches
  453.             //
  454.             TAutoSymbol* sym = pS->Class->FindId(pFD->memid, object);
  455.             if (!sym) {
  456.               UINT   cNames;
  457.               BSTR   bstrName;    // Event name(function only)
  458.               DISPID dispid;      // Event name(function only)
  459.               if (SUCCEEDED(pITypeInfo->GetNames(pFD->memid, &bstrName,
  460.                                                  1, &cNames))) {
  461.                 sym = pS->Class->Lookup(OleStr(bstrName),
  462.                                         LANGIDFROMLCID(LOCALE_USER_DEFAULT),
  463.                                         asAnyCommand, dispid);
  464.                 if (sym &&
  465.                     (sym->DispId == -1 || sym->DispId == 0) &&
  466.                     sym->TestFlag(DISPATCH_METHOD) && // check type
  467.                     pS->Class->GetArgCount(*sym) == pFD->cParams) {
  468.                   sym->DispId = pFD->memid;
  469.                 }
  470.  
  471.                 SysFreeString(bstrName);
  472.               }
  473.             }
  474.             pITypeInfo->ReleaseFuncDesc(pFD);
  475.           }
  476.         }
  477.       }
  478.       pITypeInfo->Release();
  479.     }
  480.     BCtrlI->SetEventDispatch(pID);
  481.     pID->Release();
  482.   }
  483. }
  484.  
  485. //
  486. //
  487. //
  488. TOcView*
  489. TOcControl::GetActiveControlView()
  490. {
  491.   return (TOcView*)OcDocument.GetActiveView();
  492. }
  493.  
  494. //
  495. //
  496. //
  497. TUnknown*
  498. TOcControl::CreateAutoObject(const void* obj, TAutoClass& clsInfo)
  499. {
  500.   TAppDescriptor* appDesc;
  501.   TUnknown* result = 0;
  502.   appDesc = &(OcDocument.OcApp.GetRegistrar().GetAppDescriptor());
  503.   if (appDesc) {
  504.     result = appDesc->CreateAutoObject(obj, clsInfo.GetTypeInfo(),
  505.                                        obj, clsInfo.GetTypeInfo(), 0);
  506.     if (result)
  507.       ((TServedObject*)result)->AddRef();
  508.   }
  509.   return result;
  510. }
  511.  
  512. //
  513. // Callback from TUnknown's implementation of QueryInterface
  514. //
  515. HRESULT
  516. TOcControl::QueryObject(const IID far& iid, void far* far* iface)
  517. {
  518.   PRECONDITION(iface);
  519.   HRESULT hr;
  520.  
  521.   // interfaces
  522.   //
  523.   HRSucceeded(hr = IBControlSite_QueryInterface(this, iid, iface))
  524.  
  525.   // helpers
  526.   //
  527.   || HRSucceeded(hr = TOcPart::QueryObject(iid, iface))
  528.   || (pIExtended &&(HRSucceeded(hr = pIExtended->QueryObject(iid, iface))))
  529.   ;
  530.   return hr;
  531. }
  532.  
  533.  
  534. // Extended property support
  535. //
  536. void
  537. TOcControl::SetUserName(TString& name)
  538. {
  539.   *pUserName = name;
  540. }
  541.  
  542. //
  543. //
  544. //
  545. TString&
  546. TOcControl::GetUserName()
  547. {
  548.   return *pUserName;
  549. }
  550.  
  551. //
  552. // Retrieves the extended IDispatch (exposing extended properties)
  553. //
  554. IDispatch*
  555. TOcControl::GetParent()
  556. {
  557.   IDispatch* pID = 0;
  558.   TOcView* view = OcDocument.GetActiveView();
  559.   if (view) {
  560.     if (HRSucceeded(view->QueryInterface(IID_IDispatch, &(LPVOID)pID)))
  561.       pID->Release();
  562.   }
  563.   return pID;
  564. }
  565.  
  566. //
  567. //
  568. //
  569. void
  570. TOcControl::SetLeft(long value)
  571. {
  572.   TPoint nuPos(int(value), Pos.y);
  573.   SetPos(nuPos);
  574.   UpdateRect();
  575. }
  576.  
  577. //
  578. //
  579. //
  580. void
  581. TOcControl::SetWidth(long value)
  582. {
  583.   TSize nuSize(int(value), Size.cy);
  584.   SetSize(nuSize);
  585.   UpdateRect();
  586. }
  587.  
  588. //
  589. //
  590. //
  591. void
  592. TOcControl::SetTop(long value)
  593. {
  594.   TPoint nuPos(Pos.x, int(value));
  595.   SetPos(nuPos);
  596.   UpdateRect();
  597. }
  598.  
  599. //
  600. //
  601. //
  602. void
  603. TOcControl::SetHeight(long Value)
  604. {
  605.   TSize nuSize(Size.cx, int(Value));
  606.   SetSize(nuSize);
  607.   UpdateRect();
  608. }
  609.  
  610. //
  611. //  Event support
  612. //
  613. HRESULT _IFUNC
  614. TOcControl::OnControlFocus(BOOL fGotFocus)
  615. {
  616.   TOcView* view = OcDocument.GetActiveView();
  617.   if (!view)
  618.     return HR_FAIL;
  619.  
  620.   if (fGotFocus && (view->GetActivePart()) &&
  621.      (view->GetActivePart() != this))
  622.     view->GetActivePart()->Activate (FALSE);
  623.  
  624.   TCtrlFocusEvent ev(this, fGotFocus);
  625.   view->ForwardEvent(OC_CTRLEVENT_FOCUS, &ev);
  626.   return HR_NOERROR;
  627. }
  628.  
  629. //
  630. //
  631. //
  632. HRESULT _IFUNC
  633. TOcControl::OnPropertyChanged(DISPID dispid)
  634. {
  635.   TOcView* view = OcDocument.GetActiveView();
  636.   if (!view)
  637.     return HR_FAIL;
  638.  
  639.   TCtrlPropertyEvent ev(this, dispid);
  640.   view->ForwardEvent(OC_CTRLEVENT_PROPERTYCHANGE, &ev);
  641.   return HR_NOERROR;
  642. }
  643.  
  644. //
  645. //
  646. //
  647. HRESULT _IFUNC
  648. TOcControl::OnPropertyRequestEdit(DISPID dispid)
  649. {
  650.   TOcView* view = OcDocument.GetActiveView();
  651.   if (!view)
  652.     return HR_FAIL;
  653.  
  654.   TCtrlPropertyEvent ev(this, dispid);
  655.   view->ForwardEvent(OC_CTRLEVENT_PROPERTYREQUESTEDIT, &ev);
  656.   return ev.accept ? HR_OK : HR_FALSE;
  657. }
  658.  
  659. //
  660. //
  661. //
  662. HRESULT _IFUNC
  663. TOcControl::TransformCoords(TPointL far* lpptlHimetric,
  664.                             TPointF far* lpptfContainer, DWORD flags)
  665. {
  666.   TOcView* view = OcDocument.GetActiveView();
  667.   if (!view)
  668.     return HR_FAIL;
  669.  
  670.   TCtrlTransformCoords ev(this, lpptlHimetric, lpptfContainer, flags);
  671.   if (!view->ForwardEvent(OC_VIEWTRANSFORMCOORDS, &ev)) {
  672.  
  673.     // default if not handled is to go from himetric to pixels and back again
  674.     // if you want otherwise, you should override this, or answer the
  675.     // message differently.
  676.  
  677.     HDC  dc = ::GetDC(0);
  678.     int  xPixPerInch = ::GetDeviceCaps(dc, LOGPIXELSX);
  679.     int  yPixPerInch = ::GetDeviceCaps(dc, LOGPIXELSY);
  680.     ReleaseDC(0, dc);
  681.     if (flags & XFORMCOORDS_HIMETRICTOCONTAINER) {
  682.       lpptfContainer->x =   MAP_LOGHIM_TO_PIX(lpptlHimetric->x, xPixPerInch);
  683.       lpptfContainer->y =   MAP_LOGHIM_TO_PIX(lpptlHimetric->y, yPixPerInch);
  684.     }
  685.     else if (flags & XFORMCOORDS_CONTAINERTOHIMETRIC) {
  686.       lpptlHimetric->x =   MAP_PIX_TO_LOGHIM((ULONG)lpptfContainer->x, xPixPerInch);
  687.       lpptlHimetric->y =   MAP_PIX_TO_LOGHIM((ULONG)lpptfContainer->y, yPixPerInch);
  688.     }
  689.   }
  690.   return S_OK;
  691. }
  692.  
  693. //
  694. //
  695. //
  696. HRESULT _IFUNC TOcControl::Init(UINT, IBControl*, UINT)
  697. {
  698.   return ResultFromScode(E_NOTIMPL);
  699. }
  700.  
  701. //
  702. // TOcxView Class Implementation
  703. //
  704. TOcxView::TOcxView(TOcDocument& doc, TRegList* regList, IUnknown* outer)
  705. :
  706.   TOcView(doc, regList, outer),
  707.   pBlankString(new TString(" "))
  708.   //pDisplayName(new TString("Control")),
  709.   //pScaleUnits(new TString("Control"))
  710. {
  711.   TAppDescriptor* appDesc;
  712.  
  713.   appDesc = &(OcApp.GetRegistrar().GetAppDescriptor());
  714.   if (appDesc) {
  715.     (TUnknown*)pIAmbients = appDesc->CreateAutoObject(
  716.          (VOID*)this, ClassInfo.GetTypeInfo(),
  717.          (VOID*)this, ClassInfo.GetTypeInfo(),
  718.          0);
  719.     if (pIAmbients)
  720.       pIAmbients->AddRef();
  721.   }
  722. }
  723.  
  724. //
  725. //
  726. //
  727. TOcxView::~TOcxView()
  728. {
  729.   if (pIAmbients)
  730.     pIAmbients->Release();
  731.   delete pBlankString;
  732. }
  733.  
  734. //
  735. //
  736. //
  737. HRESULT
  738. TOcxView::QueryObject(const IID far& iid, void far* far* iface)
  739. {
  740.   PRECONDITION(iface);
  741.   HRESULT hr;
  742.  
  743.   // interfaces
  744.   //
  745.  
  746.   if (pIAmbients &&(HRSucceeded(hr = pIAmbients->QueryObject(iid, iface)))) {
  747.   }
  748.   // helpers
  749.   //
  750.   else if (HRSucceeded(hr = TOcView::QueryObject(iid, iface)))
  751.   ;
  752.   return hr;
  753. }
  754.  
  755. //
  756. //
  757. //
  758. void
  759. TOcxView::SetBackColor(long)
  760. {
  761.   AmbientChanged(DISPID_AMBIENT_BACKCOLOR);
  762. }
  763.  
  764. void
  765. TOcxView::SetForeColor(long)
  766. {
  767.   AmbientChanged(DISPID_AMBIENT_FORECOLOR);
  768. }
  769.  
  770. void
  771. TOcxView::SetLocaleID(long)
  772. {
  773.   AmbientChanged(DISPID_AMBIENT_LOCALEID);
  774. }
  775.  
  776. void
  777. TOcxView::SetMessageReflect(bool)
  778. {
  779.   AmbientChanged(DISPID_AMBIENT_MESSAGEREFLECT);
  780. }
  781.  
  782. void
  783. TOcxView::SetTextAlign(short)
  784. {
  785.   AmbientChanged(DISPID_AMBIENT_TEXTALIGN);
  786. }
  787.  
  788. void
  789. TOcxView::SetUserMode(bool)
  790. {
  791.   AmbientChanged(DISPID_AMBIENT_USERMODE);
  792. }
  793.  
  794. void
  795. TOcxView::SetUIDead(bool)
  796. {
  797.   AmbientChanged(DISPID_AMBIENT_UIDEAD);
  798. }
  799.  
  800. void
  801. TOcxView::SetShowGrabHandles(bool)
  802. {
  803.   AmbientChanged(DISPID_AMBIENT_SHOWGRABHANDLES);
  804. }
  805.  
  806. void
  807. TOcxView::SetSupportsMnemonics(bool)
  808. {
  809.   AmbientChanged(DISPID_AMBIENT_SUPPORTSMNEMONICS);
  810. }
  811.  
  812. void
  813. TOcxView::SetShowHatching(bool)
  814. {
  815.   AmbientChanged(DISPID_AMBIENT_SHOWHATCHING);
  816. }
  817.  
  818. void
  819. TOcxView::SetDisplayAsDefault(bool)
  820. {
  821.   AmbientChanged(DISPID_AMBIENT_DISPLAYASDEFAULT);
  822. }
  823.  
  824. void
  825. TOcxView::SetDisplayName(TString& /*name*/)
  826. {
  827.         //pDisplayName = &name;
  828.   AmbientChanged(DISPID_AMBIENT_DISPLAYNAME);
  829. }
  830.  
  831. void
  832. TOcxView::SetScaleUnits(TString& /*unit*/)
  833. {
  834.         //pScaleUnits = &unit;
  835.   AmbientChanged(DISPID_AMBIENT_SCALEUNITS);
  836. }
  837.  
  838. void
  839. TOcxView::SetFont(IDispatch*)
  840. {
  841.   AmbientChanged(DISPID_AMBIENT_FONT);
  842. }
  843.  
  844.  
  845. void
  846. TOcxView::SetAmbBackColor(long color)
  847. {
  848.   ForwardEvent(OC_AMBIENT_SETBACKCOLOR, color);
  849. }
  850.  
  851. void
  852. TOcxView::SetAmbForeColor(long color)
  853. {
  854.   ForwardEvent(OC_AMBIENT_SETFORECOLOR, color);
  855. }
  856.  
  857. void
  858. TOcxView::SetAmbLocaleID(long localeId)
  859. {
  860.   ForwardEvent(OC_AMBIENT_SETLOCALEID, localeId);
  861. }
  862.  
  863. void
  864. TOcxView::SetAmbMessageReflect(bool msgRef)
  865. {
  866.   ForwardEvent(OC_AMBIENT_SETMESSAGEREFLECT, msgRef);
  867. }
  868.  
  869. void
  870. TOcxView::SetAmbTextAlign(short align)
  871. {
  872.   ForwardEvent(OC_AMBIENT_SETTEXTALIGN, align);
  873. }
  874.  
  875. void
  876. TOcxView::SetAmbUserMode(bool mode)
  877. {
  878.   ForwardEvent(OC_AMBIENT_SETUSERMODE, mode);
  879. }
  880.  
  881. void
  882. TOcxView::SetAmbUIDead(bool dead)
  883. {
  884.   ForwardEvent(OC_AMBIENT_SETUIDEAD, dead);
  885. }
  886.  
  887. void
  888. TOcxView::SetAmbShowGrabHandles(bool handles)
  889. {
  890.   ForwardEvent(OC_AMBIENT_SETSHOWGRABHANDLES, handles);
  891. }
  892.  
  893. void
  894. TOcxView::SetAmbSupportsMnemonics(bool mnem)
  895. {
  896.   ForwardEvent(OC_AMBIENT_SETSUPPORTSMNEMONICS, mnem);
  897. }
  898.  
  899. void
  900. TOcxView::SetAmbShowHatching(bool hatch)
  901. {
  902.   ForwardEvent(OC_AMBIENT_SETSHOWHATCHING, hatch);
  903. }
  904.  
  905. void
  906. TOcxView::SetAmbDisplayAsDefault(bool Disp)
  907. {
  908.   ForwardEvent(OC_AMBIENT_SETDISPLAYASDEFAULT, Disp);
  909. }
  910.  
  911. void
  912. TOcxView::SetAmbDisplayName(TString& name)
  913. {
  914.   ForwardEvent(OC_AMBIENT_SETDISPLAYNAME, &name);
  915. }
  916.  
  917. void
  918. TOcxView::SetAmbScaleUnits(TString& scaleUnits)
  919. {
  920.   ForwardEvent(OC_AMBIENT_SETSCALEUNITS, &scaleUnits);
  921. }
  922.  
  923. void
  924. TOcxView::SetAmbFont(IDispatch* fontDisp)
  925. {
  926.   ForwardEvent(OC_AMBIENT_SETFONT, fontDisp);
  927. }
  928.  
  929. long
  930. TOcxView::GetBackColor()
  931. {
  932.   return GetAmbientValue(OC_AMBIENT_GETBACKCOLOR, RGB(0x80, 0x80, 0x80));
  933. }
  934.  
  935.  
  936. long
  937. TOcxView::GetForeColor()
  938. {
  939.   return GetAmbientValue(OC_AMBIENT_GETFORECOLOR, RGB(0x00, 0x00, 0x00));
  940. }
  941.  
  942.  
  943. long
  944. TOcxView::GetLocaleID()
  945. {
  946.   return GetAmbientValue(OC_AMBIENT_GETLOCALEID, LOCALE_USER_DEFAULT);
  947. }
  948.  
  949.  
  950. bool
  951. TOcxView::GetMessageReflect()
  952. {
  953.   return (bool)(GetAmbientValue(OC_AMBIENT_GETMESSAGEREFLECT, false) & 0xf);
  954. }
  955.  
  956.  
  957. short
  958. TOcxView::GetTextAlign()
  959. {
  960.   return (short)(GetAmbientValue(OC_AMBIENT_GETTEXTALIGN, 0) & 0xffff);
  961. }
  962.  
  963.  
  964. bool
  965. TOcxView::GetUserMode()
  966. {
  967.   return (bool)(GetAmbientValue(OC_AMBIENT_GETUSERMODE, true) & 0xf);
  968. }
  969.  
  970.  
  971. bool
  972. TOcxView::GetUIDead()
  973. {
  974.   return (bool)(GetAmbientValue(OC_AMBIENT_GETUIDEAD, false) & 0xf);
  975. }
  976.  
  977.  
  978. bool
  979. TOcxView::GetShowGrabHandles()
  980. {
  981.   return (bool)(GetAmbientValue(OC_AMBIENT_GETSHOWGRABHANDLES, false) & 0xf);
  982. }
  983.  
  984.  
  985. bool
  986. TOcxView::GetShowHatching()
  987. {
  988.   return (bool)(GetAmbientValue(OC_AMBIENT_GETSHOWHATCHING, false) & 0xf);
  989. }
  990.  
  991.  
  992. bool
  993. TOcxView::GetDisplayAsDefault()
  994. {
  995.   return (bool)(GetAmbientValue(OC_AMBIENT_GETDISPLAYASDEFAULT, false) & 0xf);
  996. }
  997.  
  998.  
  999. bool
  1000. TOcxView::GetSupportsMnemonics()
  1001. {
  1002.   return (bool)(GetAmbientValue(OC_AMBIENT_GETSUPPORTSMNEMONICS, false) & 0xf);
  1003. }
  1004.  
  1005.  
  1006. TString&
  1007. TOcxView::GetDisplayName()
  1008. {
  1009.   TString* value;
  1010.   return ForwardEvent(OC_AMBIENT_GETDISPLAYNAME, &value) ? *value : *pBlankString;
  1011. }
  1012.  
  1013.  
  1014. TString&
  1015. TOcxView::GetScaleUnits()
  1016. {
  1017.   TString* value;
  1018.   return ForwardEvent(OC_AMBIENT_GETSCALEUNITS, &value) ? *value : *pBlankString;
  1019. }
  1020.  
  1021.  
  1022. IDispatch*
  1023. TOcxView::GetFont()
  1024. {
  1025.   IDispatch* value;
  1026.  
  1027.   // NOTE: If view handles the message, it should AddRef the font
  1028.   //
  1029.   return ForwardEvent(OC_AMBIENT_GETFONT, &value) ? value: 0;
  1030. }
  1031.  
  1032.  
  1033. void
  1034. TOcxView::AmbientChanged(DISPID dispid)
  1035. {
  1036.   // Will loop through all known controls and let them
  1037.   // know when an ambient property changes
  1038.   //
  1039.   for (TOcPartCollectionIter i(OcDocument.GetParts()); i; i++) {
  1040.     TOcPart* ocPart = (TOcPart*)i.Current();
  1041.     IBControl* CtrlI;
  1042.     if (SUCCEEDED(ocPart->QueryInterface(IID_IBControl, &(LPVOID)CtrlI))) {
  1043. #if 0
  1044.       CtrlI->Release();
  1045.       CtrlI->AmbientChanged(dispid);
  1046. #else
  1047.       CtrlI->AmbientChanged(dispid);
  1048.       CtrlI->Release();
  1049. #endif
  1050.     }
  1051.   }
  1052. }
  1053.  
  1054. long
  1055. TOcxView::GetAmbientValue(long ambientMsg, long def)
  1056. {
  1057.   uint32 value;
  1058.   return ForwardEvent(int(ambientMsg), &value) ? value : def;
  1059. }
  1060.  
  1061. //
  1062. // TOcControlEvent Class Implementation
  1063. //    Support for standard events and generic custom event
  1064. //
  1065. TOcControlEvent::TOcControlEvent()
  1066.                 :pCtrl(0), pIEvents(0)
  1067. {
  1068. }
  1069.  
  1070. TOcControlEvent::~TOcControlEvent()
  1071. {
  1072.   if (pIEvents)
  1073.     pIEvents->Release();
  1074. }
  1075.  
  1076. void
  1077. TOcControlEvent::InitEventDispatch()
  1078. {
  1079.   if (!pIEvents)
  1080.     (TUnknown far*)pIEvents = CreateAutoObject(this, ClassInfo);
  1081. }
  1082.  
  1083. TUnknown*
  1084. TOcControlEvent::CreateAutoObject(const void* obj, TAutoClass& clsInfo)
  1085. {
  1086.   if (pCtrl) {
  1087.     clsInfo.AutoIds = false;
  1088.     return (TUnknown*)pIEvents = pCtrl->CreateAutoObject(obj, clsInfo);
  1089.   }
  1090.   else
  1091.     return 0;
  1092. }
  1093.  
  1094. //
  1095. //
  1096. //
  1097. HRESULT
  1098. TOcControlEvent::ForwardClickEvent(uint msg, DISPID dispid)
  1099. {
  1100.   TOcView* view = pCtrl->GetActiveControlView();
  1101.   if (!view)
  1102.     return E_FAIL;
  1103.  
  1104.   TCtrlEvent ev(pCtrl, dispid);
  1105.   view->ForwardEvent(msg, &ev);
  1106.   return S_OK;
  1107. }
  1108.  
  1109. //
  1110. //
  1111. //
  1112. HRESULT
  1113. TOcControlEvent::ForwardMouseEvent(uint msg, DISPID id,
  1114.                                    short button, short shift,
  1115.                                    long x, long y)
  1116. {
  1117.   TOcView* view = pCtrl->GetActiveControlView();
  1118.   if (!view)
  1119.     return E_FAIL;
  1120.  
  1121.   TCtrlMouseEvent ev(pCtrl, id, button, shift, x, y);
  1122.   view->ForwardEvent(msg, &ev);
  1123.   return S_OK;
  1124. }
  1125.  
  1126. //
  1127. //
  1128. //
  1129. HRESULT
  1130. TOcControlEvent::ForwardKeyEvent(uint msg, DISPID id,
  1131.                                  short* keyCode, short shift)
  1132. {
  1133.   TOcView* view = pCtrl->GetActiveControlView();
  1134.   if (!view)
  1135.     return E_FAIL;
  1136.  
  1137.   TCtrlKeyEvent ev(pCtrl, id, *keyCode, shift);
  1138.   view->ForwardEvent(msg, &ev);
  1139.   return S_OK;
  1140. }
  1141.  
  1142. //
  1143. //
  1144. //
  1145. HRESULT
  1146. TOcControlEvent::ErrorEvent(short Number, TAutoString Description,
  1147.                             SCODE SCode, TAutoString Source,
  1148.                             TAutoString HelpFile, long HelpContext,
  1149.                             bool* CancelDisplay)
  1150. {
  1151.   TOcView* view = pCtrl->GetActiveControlView();
  1152.   if (!view)
  1153.     return E_FAIL;
  1154.  
  1155.   TCtrlErrorEvent ev(pCtrl, Number, Description, SCode, Source, HelpFile,
  1156.                      HelpContext, *CancelDisplay);
  1157.   view->ForwardEvent(OC_CTRLEVENT_ERROREVENT, &ev);
  1158.   return S_OK;
  1159. }
  1160.  
  1161. //
  1162. //
  1163. //
  1164. HRESULT
  1165. TOcControlEvent::CustomEvent(long* args)
  1166. {
  1167.   TOcView* view = pCtrl->GetActiveControlView();
  1168.   if (!view)
  1169.     return HR_FAIL;
  1170.  
  1171.   TAutoStack* autoStack = (TAutoStack*)args;
  1172.   TCtrlCustomEvent ev(pCtrl, autoStack->DispId, autoStack);
  1173.   view->ForwardEvent(OC_CTRLEVENT_CUSTOMEVENT, &ev);
  1174.   return HR_NOERROR;
  1175. }
  1176.  
  1177. //
  1178. //
  1179. //
  1180. HRESULT
  1181. TOcControlEvent::Click()
  1182. {
  1183.   return ForwardClickEvent(OC_CTRLEVENT_CLICK, DISPID_CLICK);
  1184. }
  1185.  
  1186. //
  1187. //
  1188. //
  1189. HRESULT
  1190. TOcControlEvent::DblClick()
  1191. {
  1192.   return ForwardClickEvent(OC_CTRLEVENT_DBLCLICK, DISPID_DBLCLICK);
  1193. }
  1194.  
  1195. //
  1196. //
  1197. //
  1198. HRESULT
  1199. TOcControlEvent::MouseDown(short button, short shift, long x, long y)
  1200. {
  1201.   return ForwardMouseEvent(OC_CTRLEVENT_MOUSEDOWN, DISPID_MOUSEDOWN,
  1202.                            button, shift, x, y);
  1203. }
  1204.  
  1205. //
  1206. //
  1207. //
  1208. HRESULT
  1209. TOcControlEvent::MouseMove(short button, short shift, long x, long y)
  1210. {
  1211.   return ForwardMouseEvent(OC_CTRLEVENT_MOUSEMOVE, DISPID_MOUSEMOVE,
  1212.                            button, shift, x, y);
  1213. }
  1214.  
  1215. //
  1216. //
  1217. //
  1218. HRESULT
  1219. TOcControlEvent::MouseUp(short button, short shift, long x, long y)
  1220. {
  1221.   return ForwardMouseEvent(OC_CTRLEVENT_MOUSEUP,
  1222.                            DISPID_MOUSEUP, button, shift, x, y);
  1223. }
  1224.  
  1225. //
  1226. //
  1227. //
  1228. HRESULT
  1229. TOcControlEvent::KeyDown(short far* keyCode, short shift)
  1230. {
  1231.   return ForwardKeyEvent(OC_CTRLEVENT_KEYDOWN, DISPID_KEYDOWN,
  1232.                          keyCode, shift);
  1233. }
  1234.  
  1235. //
  1236. //
  1237. //
  1238. HRESULT
  1239. TOcControlEvent::KeyUp(short far* keyCode, short shift)
  1240. {
  1241.   return ForwardKeyEvent(OC_CTRLEVENT_KEYUP, DISPID_KEYUP,
  1242.                          keyCode, shift);
  1243. }
  1244.  
  1245. //
  1246. //
  1247. //
  1248. typedef HRESULT PASCAL FAR _export (*REGPROC)();
  1249.  
  1250. //
  1251. //
  1252. //
  1253. static HRESULT
  1254. OcInvokeProc(char* libraryName, char* procName)
  1255. {
  1256.   HRESULT hr = ResultFromScode (E_FAIL);
  1257.  
  1258.   HINSTANCE libHandle = LoadLibrary(libraryName);
  1259.   if (libHandle <= HINSTANCE(HINSTANCE_ERROR))
  1260.     return hr;
  1261.  
  1262.   REGPROC dllRegProc;
  1263.   dllRegProc = (REGPROC)::GetProcAddress (libHandle, procName);
  1264.   if (dllRegProc) {
  1265.     hr = dllRegProc();
  1266.   }
  1267.  
  1268.   FreeLibrary(libHandle);
  1269.   return hr;
  1270. }
  1271.  
  1272. //
  1273. //
  1274. //
  1275. HRESULT
  1276. OcRegisterControl(char* libraryName)
  1277. {
  1278.   // NOTE: The new recommendation is to refrain from loading the control
  1279.   //       until the 'SelfRegister' string has been found in the VERSIONINFO
  1280.   //       resource...
  1281.   //
  1282.   return OcInvokeProc(libraryName, "DllRegisterServer");
  1283. }
  1284.  
  1285. //
  1286. //
  1287. //
  1288. HRESULT
  1289. OcUnregisterControl (CLSID classId)
  1290. {
  1291.   HRESULT  hr;
  1292.   LPOLESTR str;
  1293.   hr = StringFromCLSID (classId, &str);
  1294.  
  1295.   if (SUCCEEDED(hr)) {
  1296.     char temp[64];
  1297.     strcpy (temp, OleStr(str));
  1298.  
  1299.     char     key[255];
  1300.     wsprintf (key, "CLSID\\%s\\InprocServer32", temp);
  1301.     CoTaskMemFree(str);
  1302.  
  1303.     char  ocxPath[_MAX_PATH];
  1304.     long  len = sizeof(ocxPath);
  1305.     hr = (HRESULT)RegQueryValue (TRegKey::ClassesRoot,
  1306.                                 (LPCSTR)key, (LPSTR)ocxPath,
  1307.                                 (LONG FAR*)&len);
  1308.     if (SUCCEEDED(hr)) {
  1309.  
  1310.       // NOTE: The new recommendation is to refrain from loading the control
  1311.       //       until the 'SelfRegister' string has been found in the VERSIONINFO
  1312.       //       resource...
  1313.       //
  1314.       hr = OcInvokeProc(ocxPath, "DllUnregisterServer");
  1315.     }
  1316.   }
  1317.   return hr;
  1318. }
  1319.  
  1320.  
  1321.